#ifndef TABELMHS_H
#define TABELMHS_H

#include "..\mesinkata\mesinkata.h"
#include "..\Tanggal\Tanggal.h"
#include "..\LinkedListGeneralDefinition\LinkedListGeneralDefinition.h"
#include "..\Owner\Owner.h"
#include "..\Reader\Reader.h"

struct RECORD_MHS {
	string NIM; // <-- Key
	string name;
	date tglLahir;
	string kotaAsal;
	float IPK;
	int jmlSKS;
	
	struct RECORD_MHS *next;
	ownerList _ownerList;	// Di node mana saja Record ini di simpan?
};

typedef struct RECORD_MHS RecordMhs;

typedef RecordMhs* AddressMhs; 

typedef AddressMhs TabelMhs;

// DEFINISI NAMA TABEL
#define NAMATABELMHS	CharToString("Mahasiswa")

// SELEKTOR

#define NIM(R)			(R)->NIM
#define NAMA(R)			(R)->name
#define TGLLAHIR(R)		(R)->tglLahir
#define KOTAASAL(R)		(R)->kotaAsal
#define IPK(R)			(R)->IPK
#define	JMLSKS(R)		(R)->jmlSKS

#define TABELMHS_NUM_KOLOM	6
#define TABELMHS_UNDEF_VAL	-1 // Diisi pada IPK dan jmlh sks sebagai penanda bahwa IPK dan JmlSKS blm didefinisi

// DEFINISI NAMA KOLOM (DALAM BENTUK STRING)
#define Kol_NIM			CharToString("NIM")
#define Kol_Nama		CharToString("Nama")
#define Kol_TglLahir	CharToString("TglLahir")
#define Kol_KotaAsal	CharToString("KotaAsal")
#define Kol_IPK			CharToString("IPK")
#define Kol_JmlSKS		CharToString("JmlSKS")

// KONSTRUKTOR - DESTRUKTOR
TabelMhs	CreateEmptyTabelMhs();
AddressMhs	AllocateRecordMhs(string NIM, string Nama, date TglLahir, string KotaAsal);
AddressMhs	AllocateRecordMhsAdv(string NIM, string Nama, date TglLahir, string KotaAsal, AddressMhs next);
void 		DeallocateRecordMhs(RecordMhs *Mhs);

// PREDIKAT
bool		IsRecordMhsEqual(AddressMhs A, AddressMhs B);

// OPERASI
void		ChangeRecordMhsContent(AddressMhs Mhs, string NIMbaru, string Namabaru, date TglLahirBaru, string KotaAsalBaru);
/**********************************************************************************
	Mengubah isi dari Mhs
	I.S. : 	Mhs sudah dialokasi
	F.S. : 	Mhs berubah isinya
**********************************************************************************/ 

int 		GetRecordMhsSize(AddressMhs Mhs);
/**********************************************************************************
	Menghitung size dari RecordMhs
	I.S. : 	Mhs sudah dialokasi
	F.S. : 	return size dari RecordMhs
**********************************************************************************/ 

void	 	AddRecordMhs(AddressMhs Mhs, TabelMhs *TMhs);
/**********************************************************************************
	Menambahkan Mhs ke TMhs di tempat yang tepat
	I.S. : 	Mhs sudah dialokasi
	F.S. : 	TMhs berisi Mhs dan terurut membesar berdasarkan NIM
**********************************************************************************/ 

void	 	DestroyRecordMhs(AddressMhs Mhs, TabelMhs *TMhs);
/**********************************************************************************
	Mendealokasi Mhs dari TMhs.
	I.S. : 	Mhs ada di dalam TMhs
	F.S. : 	Mhs tidak ada di dalam TMhs. Mhs didealokasi.
**********************************************************************************/ 

void		AddOwnerToRecordMhs(AddressMhs Mhs, ownerAddress O);
/**********************************************************************************
	Menambah owner ke Mhs
	I.S. :	Mhs sudah dialokasi, O sudah dialokasi
	F.S. :	O ditambahkan dalam OWNERLIST(Mhs)
**********************************************************************************/ 

AddressMhs	SearchRecordMhsByNIM(string NIM, TabelMhs *TMhs);
/**********************************************************************************
	Mencari alamat Record yang memiliki NIM sama dengan NIM
	I.S. : 	Sembarang
	F.S. : 	Return address tempat record yang mengandung NIM tsb.
			Return NULL jika NIM tersebut tidak ditemukan
**********************************************************************************/ 

AddressMhs	SearchRecordMhs(AddressMhs Mhs, TabelMhs *TMhs);
/**********************************************************************************
	Mencari alamat Record Mhs dalam TMhs
	I.S. : 	Sembarang
	F.S. : 	Return address tempat record tersebut ditemukan
			Return NULL jika tidak ditemukan
**********************************************************************************/ 

bool 		EvaluateQueryTabelMhs(AddressMhs Mhs, Reader R, bool *query_succeed);
/**********************************************************************************
	Mengevaluasi Query dari user
	I.S. : 	Mhs sudah dialokasi
	F.S. : 	Return hasil query
			query_succeed berisi true apabila query dari user sesuai spesifikasi
			query_succeed berisi true apabila query dari user tidak sesuai spesifikasi
**********************************************************************************/ 

int 		CountRecordMhs(TabelMhs T);
/**********************************************************************************
	Menghitung jumlah elemen dari T
	I.S. : 	Sembarang, bisa kosong
	F.S. : 	return jumlah elemen dalam T
**********************************************************************************/ 

int			CountNodeRecordMhs(TabelMhs T, nodeAddress N);
/**********************************************************************************
	Menghitung jumlah elemen di dalam T yang memiliki owner dengan node N
	I.S. : 	Sembarang, bisa kosong
	F.S. : 	return jumlah elemen dalam T yang memiliki owner dengan node N
**********************************************************************************/ 

void		DestroyTabelMhs(TabelMhs *T);
/**********************************************************************************
	Mendealokasikan semua elemen dari list
	I.S. : 	Sembarang, list bisa kosong
	F.S. : 	TabelMhs T menjadi kosong
**********************************************************************************/

// OUTPUT - for testing
void		PrintTabelMhs(TabelMhs T);
/**********************************************************************************
	Hanya untuk ngetest
**********************************************************************************/ 

void		PrintTabelMhsHeader(bool showNIM, bool showNama, bool showTglLahir, bool showKotaAsal, bool showIPK, bool showSKS);
/**********************************************************************************
	Menampilkan Header TabelMhs ke layar.
	Contoh :
	-	PrintTabelMhsHeader(true, true, false, true, false, false) :
		NIM		Nama	KotaAsal	
	-	PrintTabelMhsHeader(false, true, false, true, true, true) :
		Nama	KotaAsal	IPK 	JmlSKS
		
	Lebar kolom :
		NIM 		: 15
		Name		: 25
		TglLahir	: 8
		KotaAsal 	: 15
		ipk 		: 5
		sks 		: 5
**********************************************************************************/ 

void		PrintRecordMhs(AddressMhs Mhs, bool showNIM, bool showNama, bool showTglLahir, bool showKotaAsal, bool showIPK, bool showSKS);
/**********************************************************************************
	Menampilkan Mhs ke layar.
	Contoh :
	-	PrintRecordMhs(Mhs, true, true, false, true, false, false) :
		13508004	Ecky Putrady	Jakarta
	-	PrintRecordMhs(Mhs, false, true, false, true, true, true) :
		Ecky Putrady	Jakarta		4.00 	46
		
	Lebar kolom :
		NIM 		: 15
		Name		: 25
		TglLahir	: 8
		KotaAsal 	: 15
		ipk 		: 5
		sks 		: 5
**********************************************************************************/ 


#endif
